package final_wearebatman_view;

import final_wearebatman_model.AND_Gate;
import final_wearebatman_model.Circuit;
import final_wearebatman_model.Composite;
import final_wearebatman_model.Generator;
import final_wearebatman_model.Inverter;
import final_wearebatman_model.Led;
import final_wearebatman_model.OR_Gate;
import final_wearebatman_model.Scope;
import final_wearebatman_model.Switch;
import final_wearebatman_model.Wire;
import java.awt.Canvas;
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Map;


//az áramkört megjelenítő osztály
public class CircuitView extends Frame {

    private Circuit circuit;
    private LinkedList<Ipaintable> components;
    private MyCanvas canvas;
    private Map table;
    private static String file;

    //főablak létrehozása
    public CircuitView() {
        super("WeAreBatman");

        this.components = new LinkedList<Ipaintable>();
        this.canvas = new MyCanvas();
        this.table = new HashMap();

        addWindowListener(new MyWindowCloser());
        Menu mFile = new Menu("File");
        Menu mSimulation = new Menu("Simulation");
        Menu mHelp = new Menu("Help");

        MenuItem mFileOpen = new MenuItem("Open...");
        MenuItem mFileExit = new MenuItem("Exit");
        mFile.add(mFileOpen).addActionListener(new MyMenuListener());
        mFile.addSeparator();
        mFile.add(mFileExit).addActionListener(new MyMenuListener());

        MenuItem mSimulationStart = new MenuItem("Start");
        MenuItem mSimulationStop = new MenuItem("Stop");
        MenuItem mSimulationTick = new MenuItem("Tick");
        mSimulation.add(mSimulationStart).addActionListener(new MyMenuListener());
        mSimulation.add(mSimulationStop).addActionListener(new MyMenuListener());
        mSimulation.add(mSimulationTick).addActionListener(new MyMenuListener());

        MenuItem mHelpHelp = new MenuItem("Help");
        mHelp.add(mHelpHelp).addActionListener(new MyMenuListener());

        MenuBar mb = new MenuBar();
        setMenuBar(mb);
        mb.add(mFile);
        mb.add(mSimulation);
        mb.add(mHelp);

        canvas.addMouseListener(new MyMouseListener());

        add(canvas);

        setSize(800, 600);
        setResizable(false);
        setLocationByPlatform(true);
        show();
    }

    //switch elem rajzolása
    public void createSwitchView(Switch s, String name, int pX, int pY, int a) {
        this.table.put(name, this.components.size());
        this.components.add(new SwitchView(s, name, this, pX, pY, a));
    }

    //szkóp rajzolása
    public void createScopeView(Scope s, String name, int pX, int pY, int a) {
        this.table.put(name, this.components.size());
        this.components.add(new ScopeView(s, name, this, pX, pY, a));
    }

    //led rajzolása
    public void createLedView(Led l, String name, int pX, int pY, int a) {
        this.table.put(name, this.components.size());
        this.components.add(new LedView(l, name, this, pX, pY, a));
    }

    //generátor rajzolása
    public void createGeneratorView(Generator gen, String name, int pX, int pY, int a) {
        this.table.put(name, this.components.size());
        this.components.add(new GeneratorView(gen, name, this, pX, pY, a));
    }

    //kompozit elem rajzolása
    public void createCompositeView(Composite c, String name, String filename, int pX, int pY) {
        this.table.put(name, this.components.size());
        this.components.add(new CompositeView(c, filename, this, pX, pY));
    }

    //vagy kapu rajzolása
    public void createOR_GateView(OR_Gate g, String name, int pX, int pY, int a) {
        this.table.put(name, this.components.size());
        this.components.add(new OR_GateView(g, name, this, pX, pY, a));
    }

    //és kapu rajzolása
    public void createAND_GateView(AND_Gate g, String name, int pX, int pY, int a) {
        this.table.put(name, this.components.size());
        this.components.add(new AND_GateView(g, name, this, pX, pY, a));
    }

    //vezeték rajzolása
    public void createWireView(Wire w, String name) {
        this.table.put(name, this.components.size());
        this.components.add(new WireView(w, name, this));
    }

    //inverter rajzolása
    public void createInverterView(Inverter inv, String name, int pX, int pY, int a) {
        this.table.put(name, this.components.size());
        this.components.add(new InverterView(inv, name, this, pX, pY, a));
    }

    //vezetékek összekötése
    public void connectWire(String wire, String p1, int outpin, String p2, int inpin) {
        //System.out.println(wire + " | " + p1 + "[" + inpin + "] " + p2 + "[" + outpin + "]");
        WireView wv = (WireView) this.components.get(Integer.parseInt(this.table.get(wire).toString()));
        Ipaintable part1 = this.components.get(Integer.parseInt(this.table.get(p1).toString()));
        Ipaintable part2 = this.components.get(Integer.parseInt(this.table.get(p2).toString()));
        wv.setStartPosition(new Point(part1.getOutputPinPosition(outpin)));
        wv.setEndPosition(new Point(part2.getInputPinPosition(inpin)));
    }

    //felület beállítása
    public void setCircuit(Circuit c) {
        this.circuit = c;
        canvas.repaint();
    }

    //tervezőfelület újrarajzolása
    public void canvasRepaint() {
        canvas.repaint();
    }

    //elemek törlése a tervezőfelületről
    public void clear() {
        this.components.clear();
    }

    class MyCanvas extends Canvas {

        @Override
        public void paint(Graphics g) {
            Graphics2D g2d = (Graphics2D) g;
            ListIterator i = components.listIterator();
            synchronized (this) {
                while (i.hasNext()) {
                    Ipaintable o = (Ipaintable) i.next();
                    o.paint(g2d);
                }
            }
        }
    }

    //egér eseményeit figyelő metódus
    class MyMouseListener implements MouseListener {

        public void mouseClicked(MouseEvent e) {
            ListIterator i = components.listIterator();
            while (i.hasNext()) {
                Ipaintable o = (Ipaintable) i.next();
                if (o.getClickArea().contains(e.getPoint())) {
                    o.onClick();
                }
            }
        }

        public void mousePressed(MouseEvent e) {
        }

        public void mouseReleased(MouseEvent e) {
        }

        public void mouseEntered(MouseEvent e) {
        }

        public void mouseExited(MouseEvent e) {
        }
    }

    //menük eseményeit figyelő metódus
    class MyMenuListener implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            if (e.getActionCommand().equals("Exit")) {
                System.exit(0);
            }
            if (e.getActionCommand().equals("Help")) {
                HelpWindow hw = new HelpWindow();
                hw.show();
            }
            if (e.getActionCommand().equals("Open...")) {
                FileDialog fd = new FileDialog(CircuitView.getFrames()[0]);
                fd.show(true);
                circuit.openFile(fd.getFile());
            }
            if (e.getActionCommand().equals("Tick")) {
                circuit.tick(1);
                canvas.repaint();
            }
            if (e.getActionCommand().equals("Start")) {
                circuit.startSimulation();
            }
            if (e.getActionCommand().equals("Stop")) {
                circuit.stopSimulation();
            }
        }
    }

    //ablak eseményeit figyelő metódus
    class MyWindowCloser implements WindowListener {

        public void windowClosing(WindowEvent e) {
            System.exit(0);
        }

        public void windowOpened(WindowEvent e) {
        }

        public void windowClosed(WindowEvent e) {
        }

        public void windowIconified(WindowEvent e) {
        }

        public void windowDeiconified(WindowEvent e) {
        }

        public void windowActivated(WindowEvent e) {
        }

        public void windowDeactivated(WindowEvent e) {
        }
    }
}
